﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Config_App
{
    public partial class _uc_CSV : UserControl
    {
        /// <summary>
        /// Property für Config
        /// </summary>
        public float[][] _I { get; set; }
        /// <summary>
        /// Property für Config
        /// </summary>
        public float[][] _O { get; set; }

        /// <summary>
        /// Property für Config
        /// Object_Cache
        /// </summary>
        public DataTable _DATA
        {
            get
            {
                return(DataTable)this._dgv_daten.DataSource;
            }
            set
            {
                this._dgv_daten.DataSource = value;
            }
        }

        /// <summary>
        /// Property für Config
        /// Object_Cache
        /// </summary>
        public DataTable _COLS
        {
            get
            {
                DataTable table = new DataTable();

                for (int iCol = 0; iCol < this._dgv_cols.Columns.Count; iCol++)
                {
                    table.Columns.Add(this._dgv_cols.Columns[iCol].Name);
                }

                foreach (DataGridViewRow row in this._dgv_cols.Rows)
                {

                    DataRow datarw = table.NewRow();

                    for (int iCol = 0; iCol < this._dgv_cols.Columns.Count; iCol++)
                    {
                        if(iCol < 2)
                            datarw[iCol] = (bool)row.Cells[iCol].Value;
                        else
                            datarw[iCol] = (string)row.Cells[iCol].Value;
                    }

                    table.Rows.Add(datarw);
                }

                return table;
            }
            set
            {
                this._dgv_cols.Rows.Clear();

                for (int i = 0; i < value.Rows.Count; i++)
                    this._dgv_cols.Rows.Add(Convert.ToBoolean(value.Rows[i].ItemArray[0]), Convert.ToBoolean(value.Rows[i].ItemArray[1]), value.Rows[i].ItemArray[2].ToString());
            }
        }

        public _uc_CSV()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Import Button Handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _cmd_import_Click(object sender, EventArgs e)
        {
            OpenFileDialog _ofd = new OpenFileDialog();
            _ofd.Filter = "CSV-Dateien|*.csv";

            if (_ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                try
                {
                    this._dgv_daten.DataSource = this.IMPORT(_ofd.FileName, this._tb_trennzeichen.Text[0], this._cb_header.Checked);
                }catch(Exception ex)
                {
                    IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.ERROR, ex.Message);

                    MessageBox.Show("Fehler beim lesen der Datei!");
                }
        }

        /// <summary>
        /// Liest Daten aus einer Datein ein und gibt die DataTable zurück.
        /// Die Cols werden in die DGV_Cols eingetragen
        /// </summary>
        /// <param name="file">DatenDatei (CSV)</param>
        /// <param name="trennung">Trennzeichen in der Datei</param>
        /// <param name="ueberschift">Enthält die erste zeile Spaltentitel?</param>
        /// <returns>Datatable für die Daten DGV</returns>
        private DataTable IMPORT(string file, char trennung, bool ueberschift)
        {
            this._dgv_cols.Rows.Clear();

            DataTable dt = new DataTable();

            using (System.IO.StreamReader sr = new System.IO.StreamReader(file, Encoding.UTF8))
            {
                // Bis zum ende der Datei
                while (!sr.EndOfStream)
                {
                    // Einze zeile auslesen und an der trennung splitten
                    string[] currentline = sr.ReadLine().Split(trennung);

                    // Wenn eine Überschrift vorhanden ist, die werte der ersten zeile in die Header setzen!
                    if(ueberschift)
                    {
                        // Erste zeile
                        if (dt.Columns.Count == 0)
                            for (int i = 0; i < currentline.Length; i++)
                            {
                                dt.Columns.Add(currentline[i]);
                                this._dgv_cols.Rows.Add(false, false, currentline[i]);
                            }
                        else
                            dt.Rows.Add(currentline);
                    }
                    else
                    {
                        // VOR der ersten zeile, header durchnummerieren, damit die Splaten verfügbar sind
                        if (dt.Columns.Count == 0)
                            for (int i = 0; i < currentline.Length; i++)
                            {
                                dt.Columns.Add("Spalte " + (i + 1));
                                this._dgv_cols.Rows.Add(false, false, "Spalte " + (i + 1));
                            }
                        // Wert adden
                        dt.Rows.Add(currentline);
                    }
                }

                sr.Close();
            }

            return dt;
        }

        /// <summary>
        /// Wendet die Konfiguraton an (handler)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _cmd_apply_Click(object sender, EventArgs e)
        {
            // Ist mindestens eine Eingabe und ein Ausgabe Spalte definiert?
            // Eine Eingabe kann auch eine Ausgaben sein! (Bewusst!!!)
            if(count("I") == 0 || count("O") == 0)
            {
                MessageBox.Show("Bitte Eingaben und Ausgaben definieren!");
                return;
            }

            try
            {
                IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "Parse I");
                this._I = this.ValueTable("I");
                IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "Parse I OK");
                IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "Parse O");
                this._O = this.ValueTable("O");
                IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "Parse O OK");
            }
            catch(Exception ex)
            {
                IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.ERROR, ex.Message);
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// Gibt ein Array[][] mit den Logischen werder der GUI zurück
        /// </summary>
        /// <param name="I_O">Input (I) oder Output(O)</param>
        /// <returns>Lernparadigmen für das Netz</returns>
        private float[][] ValueTable(string I_O)
        {
            float[][] result = new float[this._dgv_daten.Rows.Count][];

            // für jede Zeile
            for (int i = 0; i < this._dgv_daten.Rows.Count; i++)
            {
                result[i] = new float[count(I_O)];
                int ct = 0;

                // Für jede Spalte
                for (int j = 0; j < this._dgv_daten.Columns.Count; j++)
                    // Wenn die Spalte dem gewüschen typ entspricht (I/O)
                    if((bool)this._dgv_cols.Rows[j].Cells[I_O == "I" ? 0 : 1].Value)
                    {
                        result[i][ct] = (float)Convert.ToDouble(((string)this._dgv_daten.Rows[i].Cells[j].Value).Trim().Replace(',','.'));
                        ct++;
                    }
            }

            return result;
        }

        /// <summary>
        /// Zählt die Spalten, für Eingaben oder Ausgaben
        /// </summary>
        /// <param name="I_O">I(Eingabe) oder O(Ausgabe)</param>
        /// <returns></returns>
        private int count(string I_O)
        {
            int ct = 0;

            for (int i = 0; i < this._dgv_cols.Rows.Count; i++)
                // Wenn eine Eingabe gefragt ist und in der DGV_col die CB_IN gechekt ist ODER eben das gleiche für Output
                if ((I_O == "I") && (bool)this._dgv_cols.Rows[i].Cells[0].Value || (I_O == "O") && (bool)this._dgv_cols.Rows[i].Cells[1].Value)
                    ct++;

            return ct;
        }

        private void _cmd_voncert_TS_Click(object sender, EventArgs e)
        {
            if (this._dgv_cols.SelectedRows.Count != 1)
                return;

            int _last_ok = 0;
            try
            {
                for(int i=0; i<this._dgv_daten.RowCount; i++)
                {
                    IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "Original: " + this._dgv_daten.Rows[i].Cells[this._dgv_cols.SelectedRows[0].Index].Value.ToString() + " Geparst: " + DateTime.Parse(this._dgv_daten.Rows[i].Cells[this._dgv_cols.SelectedRows[0].Index].Value.ToString()).ToString());
                    long unixTimestamp = (int)Math.Round((DateTime.Parse(this._dgv_daten.Rows[i].Cells[this._dgv_cols.SelectedRows[0].Index].Value.ToString()) - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds, 0);
                    this._dgv_daten.Rows[i].Cells[this._dgv_cols.SelectedRows[0].Index].Value = unixTimestamp;

                    _last_ok = i;
                }
            }catch(Exception ex)
            {
                IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.ERROR, ex.Message);
                MessageBox.Show("Fehler beim Umwandeln (Zeile " + (_last_ok+1) + ")\r\nDaten inkonsistent!");
            }
        }
    }
}
